/*
 * Copyright (C),2015,北京新诺创科软件技术有限公司
 * author zhangmengliang
 */
package com.xnck.mfpms.service;

import com.xiaoleilu.hutool.StrUtil;
import com.xnck.mfpms.dao.QueryPartDao;
import com.xnck.mfpms.dao.RuleDao;
import com.xnck.mfpms.dao.RuleQPartDao;
import com.xnck.mfpms.entity.QueryPart;
import com.xnck.mfpms.entity.RuleInfo;
import com.xnck.mfpms.entity.RuleQueryPart;
import com.xnck.mfpms.exception.ValidateException;
import com.xnck.mfpms.util.PagerUtil;
import com.xnck.mfpms.util.ValidatorUtils;
import org.nutz.dao.Cnd;
import org.nutz.dao.sql.Criteria;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class QueryPartService {

    @Autowired
    private QueryPartDao partDao;

    @Autowired
    private RuleDao ruleDao;

    @Autowired
    private RuleQPartDao ruleQPartDao;

    public QueryPart get(String partId){
        return partDao.get(partId);
    }

    public int getsCount(String name){
        Criteria cri = Cnd.cri();
        this.getSearchCnd(cri, name);
        return partDao.searchCount(cri);
    }

    public List<QueryPart> gets(String name, String orderName, String orderType,
                                int pageSize, int beginIndex){
        Criteria cri = Cnd.cri();
        this.getSearchCnd(cri, name);
        PagerUtil.getSearchOrder(cri, QueryPart.FIELD_QUERYNAME, orderName, orderType);
        int currentPage = PagerUtil.getCurrentPage(beginIndex, pageSize);
        return partDao.searchByPage(cri, currentPage, pageSize);
    }

    /**
     * 创建数据资源
     * @param displayName 显示名称
     * @param partName 资源名称
     * @param queryName 所属查询语句名称
     * @param enable 是否启用
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public void create(String displayName, String partName, String queryName, boolean enable) throws Exception {
        this.checkPartInsertInput(displayName, partName, queryName);
        String partId = UUID.randomUUID().toString();
        partDao.insert(partId, displayName, partName, queryName, enable);
    }

    /**
     * 修改数据资源
     */
    @Transactional(rollbackFor = Exception.class)
    public void update(String id, String displayName, String partName, String queryName, boolean enable) throws Exception {
        this.checkPartUpdatetInput(id, displayName, partName, queryName);
        QueryPart part = partDao.get(id);
        if (null == part){
            throw new ValidateException("数据资源不存在");
        }
        part.setQueryname(queryName);
        part.setPartname(partName);
        part.setDisplayname(displayName);
        part.setEnable(enable);
        partDao.update(part);
    }

    /**
     * 删除数据资源
     * @param partIds
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public void deletes(String partIds) throws Exception {
        ruleQPartDao.clear(Cnd.where(RuleQueryPart.FIELD_QUERYPARTID, "in", partIds.split(",")));
        partDao.clear(Cnd.where(QueryPart.FIELD_ID, "in", partIds.split(",")));
    }

    /**
     * 数据资源与规则的关联关系
     * @param qpartId
     * @return
     * @throws Exception
     */
    public List<Map<String, Object>> getRuleNodes(String qpartId) throws Exception {
        QueryPart qpart = partDao.get(qpartId);
        if (null == qpart){
            throw new ValidateException("数据资源不存在");
        }
        List<RuleInfo> rules = ruleDao.search(Cnd.orderBy().asc(RuleInfo.FIELD_DISPLAYNAME));
        partDao.findLink(qpart, QueryPart.FIELD_RULES);
        List<Map<String, Object>> nodes = new ArrayList<Map<String, Object>>();
        for (RuleInfo rule: rules) {
            Map<String, Object> node = new HashMap<String, Object>();
            node.put("id", rule.getId());
            node.put("name", rule.getDisplayname());
            node.put("pId", rule.getParentid());
            boolean isChecked = false;
            for (RuleInfo joinRule : qpart.getRules()) {
                if (joinRule.getId().equals(rule.getId())){
                    isChecked = true;
                }
            }
            node.put("checked", isChecked);
            nodes.add(node);
        }
        return nodes;
    }

    /**
     * 关联数据资源和规则
     * @param qpartId 被关联数据资源
     * @param ruleIdStr 被关联规则列表(以逗号相隔)
     */
    @Transactional(rollbackFor = Exception.class)
    public void joinRule(String qpartId, String ruleIdStr) throws Exception {
        QueryPart qpart = partDao.get(qpartId);
        if (null == qpart){
            throw new ValidateException("数据资源不存在");
        }
        if (StrUtil.isBlank(ruleIdStr)){
            throw new ValidateException("规则不存在");
        }
        String[] ruleIds = ruleIdStr.split(",");
        partDao.clearLinks(qpart, QueryPart.FIELD_RULES);
        List<RuleInfo> rules = ruleDao.search(Cnd.where(RuleInfo.FIELD_ID, "in", ruleIds));
        if (rules.size() > 0){
            qpart.setRules(rules);
            partDao.insertRelation(qpart, QueryPart.FIELD_RULES);
        }
    }

    private void getSearchCnd(Criteria cri, String name){
        if (StrUtil.isNotBlank(name)){
            cri.where().and(
                    Cnd.exps(QueryPart.FIELD_DISPLAYNAME, "like", "%" + name + "%")
                            .or(QueryPart.FIELD_PARTNAME, "like", "%" + name + "%")
                            .or(QueryPart.FIELD_QUERYNAME, "like", "%" + name + "%"));
        }
    }

    private void checkPartInsertInput(String displayName, String partName, String queryName) throws Exception {
        if (ValidatorUtils.isEmpty(displayName)){
            throw new ValidateException("条件说明不能为空");
        }
        if(displayName.getBytes().length < 4 || displayName.getBytes().length > 50){
            throw new ValidateException("条件说明应由4-50个字符组成");
        }
        if (ValidatorUtils.isEmpty(partName)){
            throw new ValidateException("条件代码不能为空");
        }
        if(partName.getBytes().length < 4 || partName.getBytes().length > 50){
            throw new ValidateException("条件代码应由4-50个字符组成");
        }
        if (ValidatorUtils.isEmpty(queryName)){
            throw new ValidateException("所属语句名称不能为空");
        }
        if(queryName.getBytes().length < 4 || queryName.getBytes().length > 50){
            throw new ValidateException("所属语句名称应由4-50个字符组成");
        }
        List<QueryPart> parts = partDao.search(Cnd.where(QueryPart.FIELD_PARTNAME, "=", partName)
                .and(QueryPart.FIELD_QUERYNAME, "=", queryName));
        if (parts.size() > 0){
            throw new ValidateException("指定的语句下相同的条件片段已存在");
        }
    }

    private void checkPartUpdatetInput(String id, String displayName, String partName, String queryName) throws Exception {
        if (ValidatorUtils.isEmpty(displayName)){
            throw new ValidateException("条件说明不能为空");
        }
        if(displayName.getBytes().length < 4 || displayName.getBytes().length > 50){
            throw new ValidateException("条件说明应由4-50个字符组成");
        }
        if (ValidatorUtils.isEmpty(partName)){
            throw new ValidateException("条件代码不能为空");
        }
        if(partName.getBytes().length < 4 || partName.getBytes().length > 50){
            throw new ValidateException("条件代码应由4-50个字符组成");
        }
        if (ValidatorUtils.isEmpty(queryName)){
            throw new ValidateException("所属语句名称不能为空");
        }
        if(queryName.getBytes().length < 4 || queryName.getBytes().length > 50){
            throw new ValidateException("所属语句名称应由4-50个字符组成");
        }
        List<QueryPart> parts = partDao.search(Cnd.where(QueryPart.FIELD_PARTNAME, "=", partName)
                .and(QueryPart.FIELD_QUERYNAME, "=", queryName)
                .and(QueryPart.FIELD_ID, "<>", id));
        if (parts.size() > 0){
            throw new ValidateException("指定的语句下相同的条件片段已存在");
        }
    }
}
